package core

import (
	"context"
	"os/exec"
)

type Transfer struct {
	path    string //rtsp:xxxxxx
	scale   string //scale=640:360,setsar=1:1
	cmd     *exec.Cmd
	working bool
	channel *Channel
}

func NewTransfer(channel *Channel, path string) *Transfer {
	return &Transfer{
		path:    path,
		scale:   "scale=640:360,setsar=1:1",
		channel: channel,
	}
}

func (o *Transfer) Encode(ctx context.Context) {
	o.working = true
	args := []string{
		"-rtsp_transport", "tcp",
		"-allowed_media_types", "video",
		"-use_wallclock_as_timestamps", "1",
		"-i", o.path,
		"-f", "mpegts",
		"-codec:v", "mpeg1video",
		"-b:v", "1000k",
		"-bf", "0",
		"-vf", o.scale,
		"-r", "25",
		"-",
	}
	cmd := exec.Command(G.App.FFMpeg, args...)
	defer func() {
		G.Log.Info("syscall.Kill ", cmd.Process.Pid)
		// 关闭ffmpeg子进程
		if err := cmd.Process.Kill(); err != nil {
			G.Log.Errorf("Kill command error: %v", err)
		}
		// 需要等待子进程关闭，否则子进程会成为僵尸进程 <defunct>
		if err := cmd.Wait(); err != nil {
			G.Log.Errorf("Wait Kill command error: %v", err)
		}
	}()

	stdout, err := cmd.StdoutPipe()
	if err != nil {
		o.channel.OnError(err)
		return
	}

	o.cmd = cmd

	chunk := make([]byte, 51200)
	if err := cmd.Start(); err != nil {
		o.channel.OnError(err)
		return
	}

	for {
		if !o.working {
			return
		}
		select {
		case <-ctx.Done():
			return
		default:
		}
		len, err := stdout.Read(chunk)
		// G.Log.Debug("ffm read:", o.working, len)
		if err != nil {
			o.channel.OnError(err)
			return
		}
		o.channel.OnMediaData(chunk[:len])
	}
}

func (t *Transfer) Close(cancel context.CancelFunc) {
	t.working = false
	if cancel != nil {
		cancel()
	}
}
